Ch2. 렉시컬 스코프
스코프의 종류
- 렉시컬 스코프 (Lexical Scope)
- 동적 스코프 (Dynamic Scope)
→ JavaScript는 렉시컬 스코프를 사용한다.
function foo() {
console.log(a);
}
function bar() {
var a = 3;
foo();
}
var a = 2;
bar(); // 출력: 2 (렉시컬 기준)
2.1 렉스타임
렉시컬 스코프는 코드가 작성된 시점에 스코프가 결정된다.
function foo(a) {
var b = a * 2;
function bar(c) {
console.log(a, b, c);
}
bar(b * 3);
}
foo(2); // 2, 4, 12
- 총 3개의 스코프 생성됨
- 전체 범위
- foo 내부
- bar 내부
→ 스코프는 겹치는 게 아니라 포함되는 구조 (버블 형태)
섀도잉 (Shadowing)
- 안쪽 스코프의 변수가 바깥쪽 변수 이름을 가리는 현상
- 전역
a를window.a로 접근 가능하긴 함
2.2 렉시컬 속이기 (스코프 위조)
렉시컬 스코프를 동적으로 바꾸는 유일한 방법:
evalwith
2.2.1 eval
function foo(str, a) {
eval(str);
console.log(a, b);
}
var b = 2;
foo("var b = 3;", 1); // 1, 3
console.log(b); // 2
eval은 그 자리에서 코드를 실행시켜 렉시컬 스코프를 위조함- strict mode에서는 자체 스코프 생성 → 바깥 영향 없음
2.2.2 with
var obj = { a: 1, b: 2, c: 3 };
with (obj) {
a = 3;
b = 4;
c = 5;
}
function foo(obj) {
with (obj) {
a = 2;
}
}
var o1 = { a: 1 };
var o2 = { b: 1 };
foo(o1); // o1.a → 2
foo(o2); // o2.a → undefined, 전역 a 생성됨!
with는 별도 스코프 생성- 동적 레퍼런스 → 성능 최적화 방해
2.2.3 성능 저하
eval,with은 엔진이 컴파일 시 변수 위치를 미리 예측하지 못하게 함- 최적화 불가 → 퍼포먼스 저하
- 사용 지양 권장
2.3 정리
- JavaScript는 렉시컬 스코프를 기반으로 한다
eval,with은 스코프를 속일 수 있지만 성능 저하 유발- 코드는 선언 위치에 따라 스코프가 고정된다